from tkinter import Toplevel, ttk, Canvas, BooleanVar, StringVar, DoubleVar, IntVar, messagebox
from utils.Logger import Logger
from typing import Dict, Optional, Any

class SettingsWindow:
    def __init__(self, config):
        """设置窗口初始化"""
        self.logger = Logger(__name__)
        self.config = config
        self.logger.info("SettingsWindow initialized")

    def show(self, parent):
        """显示设置窗口"""
        try:
            self.logger.debug("Creating settings window")
            self.window = Toplevel(parent)
            self.window.title("设置")
            self.window.geometry("600x400")
            
            # 创建Tab控件
            tab_control = ttk.Notebook(self.window)
            
            # 创建AI服务设置Tab
            ai_tab = ttk.Frame(tab_control)
            tab_control.add(ai_tab, text='AI服务')
            
            # 创建滚动区域
            ai_canvas = Canvas(ai_tab)
            ai_scrollbar = ttk.Scrollbar(ai_tab, orient="vertical", command=ai_canvas.yview)
            ai_scrollable_frame = ttk.Frame(ai_canvas)
            
            # AI服务Tab滚动区域配置
            ai_scrollable_frame.bind(
                "<Configure>",
                lambda e: ai_canvas.configure(
                    scrollregion=ai_canvas.bbox("all")
                )
            )
            
            ai_canvas.create_window((0, 0), window=ai_scrollable_frame, anchor="nw")
            ai_canvas.configure(yscrollcommand=ai_scrollbar.set)
            
            # AI服务Tab布局
            ai_canvas.pack(side="left", fill="both", expand=True)
            ai_scrollbar.pack(side="right", fill="y")
            
            # AI服务设置
            ai_frame = ttk.LabelFrame(ai_scrollable_frame, text="AI 服务设置")
            ai_frame.pack(fill="x", padx=5, pady=5)
            
            # 服务提供商
            ttk.Label(ai_frame, text="服务提供商:").grid(row=0, column=0, sticky="w", padx=5, pady=2)
            self.provider_var = StringVar()
            self.provider_combobox = ttk.Combobox(ai_frame, 
                                                textvariable=self.provider_var,
                                                values=["DeepSeek", "Zhipu", "Qwen"],
                                                state="readonly",
                                                width=37)
            self.provider_combobox.grid(row=0, column=1, padx=5, pady=2)
            self.provider_combobox.set(self.config.get_current_provider())
            self.provider_combobox.bind("<<ComboboxSelected>>", self._update_provider_settings)
            self.logger.debug("AI provider selection initialized")
            
            # 模型ID
            ttk.Label(ai_frame, text="模型ID:").grid(row=1, column=0, sticky="w", padx=5, pady=2)
            self.model_id_var = StringVar(value=self.config.get("model_id", ""))
            self.model_id_combobox = ttk.Combobox(ai_frame, 
                                                textvariable=self.model_id_var,
                                                state="readonly",
                                                width=37)
            self.model_id_combobox.grid(row=1, column=1, padx=5, pady=2)
            self.logger.debug("Model ID setting initialized")
            
            # API Key
            ttk.Label(ai_frame, text="API Key:").grid(row=2, column=0, sticky="w", padx=5, pady=2)
            self.api_key_var = StringVar(value=self._format_api_key(self.config.get(f"api_keys.{self.provider_var}", "")))
            self.api_key_entry = ttk.Entry(ai_frame, textvariable=self.api_key_var, width=37)
            self.api_key_entry.grid(row=2, column=1, padx=5, pady=2)
            # self.api_key_entry.config(show="*") #Initially hide the API key
            self.api_key_entry.bind("<FocusIn>", self._show_full_api_key)
            self.api_key_entry.bind("<FocusOut>", self._hide_api_key)
            self.logger.debug("API Key setting initialized")
            
            # 模型参数设置
            model_frame = ttk.LabelFrame(ai_scrollable_frame, text="模型参数")
            model_frame.pack(fill="x", padx=5, pady=5)
            
            # 温度
            ttk.Label(model_frame, text="温度 (0-1):").grid(row=0, column=0, sticky="w", padx=5, pady=2)
            self.temperature_var = DoubleVar(value=self.config.get("temperature", 0.7))
            self.temperature_scale = ttk.Scale(model_frame, from_=0, to=1, variable=self.temperature_var, length=200)
            self.temperature_scale.grid(row=0, column=1, padx=5, pady=2)
            self.temperature_entry = ttk.Entry(model_frame, textvariable=self.temperature_var, width=10)
            self.temperature_entry.grid(row=0, column=2, padx=5, pady=2)
            self.logger.debug("Temperature setting initialized")
            
            # 最大token数
            ttk.Label(model_frame, text="最大token数:").grid(row=1, column=0, sticky="w", padx=5, pady=2)
            self.max_tokens_var = IntVar(value=self.config.get("max_tokens", 1000))
            self.max_tokens_scale = ttk.Scale(model_frame, from_=100, to=4000, variable=self.max_tokens_var, length=200)
            self.max_tokens_scale.grid(row=1, column=1, padx=5, pady=2)
            self.max_tokens_entry = ttk.Entry(model_frame, textvariable=self.max_tokens_var, width=10)
            self.max_tokens_entry.grid(row=1, column=2, padx=5, pady=2)
            self.logger.debug("Max tokens setting initialized")
            
            # Top P
            ttk.Label(model_frame, text="Top P (0-1):").grid(row=2, column=0, sticky="w", padx=5, pady=2)
            self.top_p_var = DoubleVar(value=self.config.get("top_p", 0.9))
            self.top_p_scale = ttk.Scale(model_frame, from_=0, to=1, variable=self.top_p_var, length=200)
            self.top_p_scale.grid(row=2, column=1, padx=5, pady=2)
            self.top_p_entry = ttk.Entry(model_frame, textvariable=self.top_p_var, width=10)
            self.top_p_entry.grid(row=2, column=2, padx=5, pady=2)
            self.logger.debug("Top P setting initialized")
            
            # 流式输出
            self.stream_var = BooleanVar(value=self.config.get("stream", True))
            ttk.Checkbutton(model_frame, text="流式输出", variable=self.stream_var).grid(row=3, column=0, columnspan=3, sticky="w", padx=5, pady=2)
            self.logger.debug("Stream output setting initialized")
            
            # 创建编辑器设置Tab
            editor_tab = ttk.Frame(tab_control)
            tab_control.add(editor_tab, text='编辑器')
            
            # 编辑器设置
            editor_frame = ttk.LabelFrame(editor_tab, text="编辑器设置")
            editor_frame.pack(fill="x", padx=5, pady=5)
            
            # 字体
            ttk.Label(editor_frame, text="字体:").grid(row=0, column=0, sticky="w", padx=5, pady=2)
            self.font_family_entry = ttk.Entry(editor_frame, width=20)
            self.font_family_entry.grid(row=0, column=1, padx=5, pady=2)
            self.font_family_entry.insert(0, self.config.get("font_family", "Arial"))
            self.logger.debug("Font family setting initialized")
            
            # 字体大小
            ttk.Label(editor_frame, text="字体大小:").grid(row=1, column=0, sticky="w", padx=5, pady=2)
            self.font_size_entry = ttk.Entry(editor_frame, width=10)
            self.font_size_entry.grid(row=1, column=1, padx=5, pady=2)
            self.font_size_entry.insert(0, str(self.config.get("font_size", 18)))
            self.logger.debug("Font size setting initialized")
            
            # 日志级别
            ttk.Label(editor_frame, text="日志级别:").grid(row=2, column=0, sticky="w", padx=5, pady=2)
            self.log_level_var = StringVar()
            self.log_level_combobox = ttk.Combobox(editor_frame, 
                                                 textvariable=self.log_level_var,
                                                 values=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
                                                 state="readonly",
                                                 width=10)
            self.log_level_combobox.grid(row=2, column=1, padx=5, pady=2)
            self.log_level_combobox.set(self.config.get("log_level", "INFO"))
            self.logger.debug("Log level setting initialized")
            
            # 显示Tab控件
            tab_control.pack(expand=1, fill="both", padx=10, pady=10)
            
            # 保存按钮
            save_button = ttk.Button(self.window, text="保存设置", command=self._save_settings)
            save_button.pack(side="bottom", pady=10)
            
            self.logger.info("Settings window shown successfully")
        except Exception as e:
            self.logger.critical(f"Failed to show settings window: {str(e)}", exc_info=True)
            raise
    
    def _update_provider_settings(self, event=None):
        """根据选择的提供商更新设置"""
        try:
            provider = self.provider_var.get()
            self.config.set_current_provider(provider)
            
            # 根据提供商设置模型ID选项
            model_options = {
                "DeepSeek": ["deepseek-chat", "deepseek-reasoner"],
                "Zhipu": ["glm-4-flash", "glm-4-plus"], 
                "Qwen": ["qwen-turbo", "qwen-plus"]
            }
            self.model_id_combobox['values'] = model_options.get(provider, [])
            self.model_id_combobox.current(0)
            self.logger.debug(f"Updated provider to: {provider}, set model ID options")
        except Exception as e:
            self.logger.error(f"Failed to update provider settings: {str(e)}", exc_info=True)
    
    def _show_full_api_key(self, event=None):
        """显示完整的API Key"""
        try:
            current_provider = self.provider_var.get().lower()
            api_key = self.config.get(f"api_keys.{current_provider}", "")
            self.original_api_key = api_key  # 保存原始值
            self.api_key_var.set(api_key)
        except Exception as e:
            self.logger.error(f"Failed to show full API key: {str(e)}")
    
    def _hide_api_key(self, event=None):
        """隐藏API Key中间部分"""
        try:
            # 如果是新输入的值，更新原始值
            if self.api_key_entry.get() != self._format_api_key(self.original_api_key):
                self.original_api_key = self.api_key_entry.get()
            # 显示加密版本
            self.api_key_var.set(self._format_api_key(self.original_api_key))
        except Exception as e:
            self.logger.error(f"Failed to hide API key: {str(e)}")

    def _save_settings(self):
        """保存设置"""
        try:
            self.logger.info("Saving settings...")
            
            # 保存AI服务设置
            current_provider = self.provider_var.get().lower()
            self.config.set_current_provider(current_provider)
            
            # 使用保存的原始 API key 值
            self.config.set_api_key(current_provider, self.original_api_key)
            
            self.config.set("model_id", self.model_id_var.get())
            
            # 保存模型参数
            self.config.set("temperature", float(self.temperature_entry.get()))
            self.config.set("max_tokens", int(self.max_tokens_entry.get()))
            self.config.set("top_p", float(self.top_p_entry.get()))
            self.config.set("stream", self.stream_var.get())
            
            # 保存编辑器设置
            self.config.set("font_family", self.font_family_entry.get())
            self.config.set("font_size", int(self.font_size_entry.get()))
            
            # 保存日志设置
            self.config.set("log_level", self.log_level_var.get())
            
            # 保存配置
            self.config._save_config()
            self.logger.info("Settings saved successfully")
            
            # 应用日志级别设置
            self.logger.set_level(self.log_level_var.get())
            self.logger.debug(f"Log level set to: {self.log_level_var.get()}")
            
            messagebox.showinfo("成功", "设置已保存")
        except ValueError as e:
            self.logger.error(f"Invalid setting value: {str(e)}", exc_info=True)
            messagebox.showerror("错误", f"设置值格式错误: {str(e)}")
        except Exception as e:
            self.logger.critical(f"Failed to save settings: {str(e)}", exc_info=True)
            messagebox.showerror("错误", f"保存设置失败: {str(e)}")
    
    def _format_api_key(self, api_key: str) -> str:
        """格式化API Key显示，仅显示前8位和后8位"""
        if len(api_key) <= 16:
            return api_key
        return f"{api_key[:8]}****{api_key[-8:]}"
